package com.yongqi.duocai.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.api.R;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.gson.Gson;
import com.yongqi.duocai.config.WechatConfig;
import com.yongqi.duocai.entity.Order;
import com.yongqi.duocai.entity.Refund;
import com.yongqi.duocai.entity.User;
import com.yongqi.duocai.entity.result.OrderInfoResult;
import com.yongqi.duocai.exception.BusinessException;
import com.yongqi.duocai.exception.ResponseEnum;
import com.yongqi.duocai.service.OrderService;
import com.yongqi.duocai.service.RefundService;
import com.yongqi.duocai.service.UserService;
import com.yongqi.duocai.utils.*;
import io.swagger.annotations.Api;


import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 1.描述（@desc）：
 * 2.作者（@author）：夏亮辉
 * 3.日期（@date）：2021年06月22  17:19
 * 4.版本（@version）：1.0.0
 * 5.版权：
 */
@RestController
@Api(tags = "WeChatPayController")
@Slf4j
public class WeChatPayController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private RefundService refundService;

    @Autowired
    private UserService userService;

    @Value("${weixinconfig.weixinappID}")
    private String appId;

    @Value("${weixinconfig.weixinappSercret}")
    private String appSecret;

    private String no="18722557202107010312491";

    private Integer userId=1;

    @PostMapping("/wxPay")
    @ApiOperation(value = "微信支付")
    public JsonResult pay( String no, Integer userId, String total_fee, String code) throws UnknownHostException {
        JsonResult jsonResult = new JsonResult();

        this.no = no;

        this.userId = userId;

        // 登陆凭证校验。通过 wx.login 接口获得临时登陆凭证 code 后传到开发者服务器调用此接口完成登陆流程
        String url = "https://api.weixin.qq.com/sns/jscode2session";
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("appid",appId);
        param.add("secret",appSecret);
        param.add("js_code",code);
        param.add("grant_type","anuthorization_code");

        // RestTemplate 的请求
        // 开发者服务器 登陆凭证校验接口 appid + appsercret + code
        JSONObject forObject = RestTemplateUtil.doPost(url,param);

        // 接收微信接口服务 获取返回的参数
        String openid = forObject.getString("openid");
        if(StringUtils.isEmpty(openid)){
            throw new BusinessException(ResponseEnum.APPID_INVALID_ERROR);
        }

        Map<String, String> requstDataMap = new HashMap<>();
        requstDataMap.put("appid", appId); //小程序ID
        requstDataMap.put("mch_id", "1578360971"); // 商户号
        // 生成随机字符串
        String noceStr = WXPayUtil.generateNonceStr();
        requstDataMap.put("nonce_str", noceStr); //随机字符串
        requstDataMap.put("body", "甬棋-多彩贵州酒"); // 商品描述
        requstDataMap.put("out_trade_no", no); // 商品订单号
        requstDataMap.put("total_fee", total_fee); // 订单金额
        // 获取主机 IP 地址
        InetAddress localHost = InetAddress.getLocalHost();
        String hostAddress = localHost.getHostAddress();
        requstDataMap.put("spbill_create_ip", hostAddress); // 终端IP
        requstDataMap.put("notify_url", "http://122.112.141.54:9898/wxpayNotity"); // 通知地址
        requstDataMap.put("trade_type", "JSAPI"); // 交易类型
        requstDataMap.put("openid", openid); // openId

        // 生成签名值
        String signValue = null;
        try {
            signValue = WXPayUtil.generateSignature(requstDataMap, "cv58dkd9c9x74qxs7izwgaef2psuj2lg");
            requstDataMap.put("sign", signValue); // 签名

            // 将类型为map 的参数转换为xml格式
            String requestDataXml = WXPayUtil.mapToXml(requstDataMap);

            System.out.println(requestDataXml);

            // 发送调用统一下单 API 接口，响应的是 XML 格式的结果
            String responseDataXml = HttpClientUtils.doPostByXml("https://api.mch.weixin.qq.com/pay/unifiedorder", requestDataXml).trim();

            // 将 xml 转化成 map
            Map<String, String> responseMap = WXPayUtil.xmlToMap(responseDataXml);

            // 获取 return_code
            String return_code = responseMap.get("return_code");
            String result_code = responseMap.get("result_code");
            //判断通信是否成功
            if(return_code.equals("SUCCESS") && result_code.equals("SUCCESS")){

                String appId = responseMap.get("appid");
                String pack = responseMap.get("prepay_id");
                String timeStamp = String.valueOf(System.currentTimeMillis());
                String params = "appId=".concat(appId)
                                .concat("&nonceStr=").concat(noceStr)
                                .concat("&package=prepay_id=").concat(pack)
                                .concat("&signType=").concat("MD5")
                                .concat("&timeStamp=").concat(timeStamp)
                                .concat("&key=").concat("cv58dkd9c9x74qxs7izwgaef2psuj2lg");
                String paySign = WXPayUtil.MD5(params);


                // 拼接小程序拉起微信支付的参数
                Map<String, String> parameMap = new HashMap<>();
                parameMap.put("timeStamp",timeStamp);
                parameMap.put("nonceStr",noceStr);
                parameMap.put("package","prepay_id=".concat(pack));
                parameMap.put("signType","MD5");
                parameMap.put("paySign",paySign);

                jsonResult.setCode(200);
                jsonResult.setData(parameMap);

            }else if(responseMap.get("err_code").equals("INVALID_REQUEST")){
                jsonResult.setResponse(ResponseEnum.WXPAY_PARAM_ERROR);
            } else {
                jsonResult.setCode(200);
                jsonResult.setError(responseMap.get("err_code"));
                jsonResult.setMessage(responseMap.get("err_code_des"));
            }

        } catch (Exception e) {
            e.printStackTrace();
        }


        return jsonResult;
    }


    @PostMapping("/wxpay/notify")
    @ApiOperation(value = "微信支付成功的回调")
    public JsonResult payNotify() {
        JsonResult jsonResult = new JsonResult();
        boolean res = false;
        // 查询根据订单号查询订单
        List<Order> orders = orderService.queryByCondition(userId, no);
        for (Order o : orders){
            o.setPayTime(LocalDateTime.now());
            o.setState(2);
            res = orderService.updateById(o);
        }
        // 发送邮箱
        EmailUtils.SendSimpleEmail("多彩贵州下单通知", "当前订单号：" + orders.get(0).getNo().concat("支付成功请及时处理"));
        User user = userService.getById(userId);
        if(user.getMonetary() == null){
            // 设置
            user.setMonetary(new BigDecimal(0.0));
        }
        user.setMonetary(user.getMonetary().add(orders.get(0).getTotal()));
        res = userService.updateById(user);
        if(res){
            jsonResult.setCode(200);
            jsonResult.setMessage("修改成功！！");
        }
        return jsonResult;
    }


    @PostMapping("/wxpay/refund")
    @ApiOperation(value = "微信退款")
    public JsonResult refund(Integer userId, String no) throws Exception {
        JsonResult jsonResult = new JsonResult();
        List<Order> orders = orderService.queryByCondition(userId, no);
        if(orders.size() == 0){
            jsonResult.setMessage("订单与用户id不匹配。");
            return jsonResult;
        }
        List<Order> newList = orders.stream()
                .filter(ListUtils.distinctByKey(Order::getNo)).collect(Collectors.toList());
        if(newList.get(0).getState() == 2){
            String reundNo = OrderNumUtils.createRefNum(userId);

            String total_fee = newList.get(0).getTotal().multiply(new BigDecimal(100)).toString();

            total_fee = total_fee.substring(0,total_fee.indexOf("."));

            Map<String, String> requestMap = new HashMap<>();
            requestMap.put("appid", appId);
            requestMap.put("mch_id", "1578360971");
            // 生成随机字符串
            String noceStr = WXPayUtil.generateNonceStr();
            requestMap.put("nonce_str", noceStr);
            requestMap.put("out_trade_no", no);
            requestMap.put("out_refund_no", reundNo);
            requestMap.put("total_fee",total_fee);
            requestMap.put("refund_fee", total_fee);
            // 生成签名值
            String signValue = null;
            signValue = WXPayUtil.generateSignature(requestMap, "cv58dkd9c9x74qxs7izwgaef2psuj2lg");
            requestMap.put("sign", signValue);
            // 将map 变为 xml
            String requestXml = WXPayUtil.mapToXml(requestMap);

            // 微信退款申请
            String result = WXPayUtils.doWechatRefund("https://api.mch.weixin.qq.com/secapi/pay/refund", requestXml);
            if(result == null){
                throw  new BusinessException(ResponseEnum.WXPAY_ORDER_ERROR);
            }
            // 将 xml 转换为 map
            Map<String, String> map = WXPayUtil.xmlToMap(result);
            String result_code = map.get("result_code");
            if(result_code.equals("FAIL")){
                jsonResult.setCode(200);
                jsonResult.setMessage("退款失败！请联系管理员");
                return jsonResult;
            }else if(result_code.equals("SUCCESS")){
                for (Order o : orders){
                    o.setState(6);
                    o.setEndTime(LocalDateTime.now());
                    orderService.updateById(o);
                }
                Order order = newList.get(0);
                EmailUtils.SendSimpleEmail("多彩贵州订单退款通知", "当前订单号：" + order.getNo().concat("申请退款成功请及时处理"));
                Refund refund = new Refund();
                refund.setOrderNo(order.getNo());
                refund.setNo(reundNo);
                refund.setState(4);
                refund.setIsGoods(false);
                refund.setAllowMoney(order.getTotal());
                refund.setActualMoney(order.getTotal());
                refundService.save(refund);
                jsonResult.setCode(200);
                jsonResult.setMessage("退款已提交微信处理，微信零钱会在20分钟内到账。银行卡1-3个工作日到账。");
            }
            return jsonResult;
        }else {
            jsonResult.setMessage("未找到符合状态的订单");
        }


        return jsonResult;
    }

}
